

module ALU(
    input [2:0] funct3,
    input [6:0] op,
    input bit_th,
    input [31:0] rv1,
    input [31:0] rv2,
    input [3:0] we, 
    input signed [31:0] imm,
    input [31:0] iaddr,
    input pc_replace_old,
    input flag_old,
    output reg [31:0] regdata,
    output reg [31:0] pc,
    output reg[31:0] daddr,
    output reg [3:0] we_final,
    output reg [31:0] dwdata,
    output reg[31:0] pc_new,
    output reg pc_replace,
    output reg pc_JALR
);

    wire [31:0] regdata_R, regdata_I, iaddr_val;
    wire jump_flag;


    initial begin
        pc_new = 0;
        pc_replace = 0;
        pc_JALR = 0;
    end

    always @(*) begin
	pc_new=0;
	pc_replace=0;
	pc_JALR=0;
        case (op)
            7'b0110011: begin // R-type
                regdata = regdata_R;
                we_final = we;
            end
            7'b0010011: begin // I-type
                regdata = regdata_I;
                we_final = we;
            end
            7'b0000011: begin // 
                daddr = rv1 + imm;
                we_final = we;
            end
            7'b0100011: begin // S
                daddr = rv1 + imm;
                case (funct3)
                    3'b000: dwdata = {4{rv2[7:0]}};
                    3'b001: dwdata = {2{rv2[15:0]}};
                    3'b010: dwdata = rv2;
                endcase
                we_final = we; //<< daddr[1:0];
            end
            7'b1100011: begin // Branch
                pc_new = iaddr_val;
                we_final = we;
		        pc_replace = (pc_replace_old | !flag_old) ? 0 : jump_flag;
            end
            7'b1100111: begin // JALR
                regdata = iaddr + 4; //iaddr + 4
                pc_new =  rv1 + imm;          //(rv1 + imm) & 32'hfffffffe; //autochip ~1
                we_final = we;
                pc_replace = (pc_replace_old | !flag_old) ? 0 : 1;
		        pc_JALR = 1;
            end
            7'b1101111: begin // JAL
                regdata = iaddr + 4;    //iaddr + 4
                pc_new = imm - 12;     //imm - 12
                we_final = we;
                pc_replace = (pc_replace_old | !flag_old) ? 0 : 1;
            end
            7'b0010111: begin // AUIPC
                regdata = iaddr + imm;    //iaddr + imm
                we_final = we;
            end
            7'b0110111: begin // LUI
                regdata = imm;
                we_final = we;
            end
            default: begin // Error handling
                regdata = 32'hDEADBEEF;
                we_final = 4'b0000;
            end
        endcase
    end
   R_type r1(funct3, bit_th, rv1, rv2, regdata_R);
    I_type i1(funct3, bit_th, rv1, imm, regdata_I);
    B_type b1(funct3, iaddr, imm, rv1, rv2, iaddr_val, jump_flag);
endmodule
